import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { EventStreamContentType, fetchEventSource } from '@microsoft/fetch-event-source'
import { AppVersion } from '@/framework/constant/Common'

class RetriableError extends Error {
}

class FatalError extends Error {
}

export class ChatApi {
  static dialogList(param = { page_no: 1, page_size: 10 }) {
    return request.post('/chat-api/v1/gpt/dialog/list', param)
  }

  static create(data) {
    return request.post('/chat-api/v1/gpt/dialog/create', data)
  }

  static remove(id) {
    return request.post('/chat-api/v1/gpt/dialog/remove', { id })
  }

  static update(data) {
    return request.post('/chat-api/v1/gpt/dialog/update', data)
  }

  static stop() {
    return request.post('/chat-api/v1/gpt/dialog/chat/stop')
  }

  static chat(data, { signal }, resolve, reject, itemIdCallback = null) {
    // return axios.post('/chat-api/v1/gpt/dialog/chat', data, {
    //   responseType: 'stream',
    //   headers: { 'Authorization': getToken() }
    // })
    fetchEventSource('/chat-api/v1/gpt/dialog/chat', {
      method: 'POST',
      signal,
      openWhenHidden: true,
      body: JSON.stringify(data),
      headers: {
        'Authorization': getToken(),
        'token': getToken(),
        'AppVersion': AppVersion,
        'Content-Type': 'application/json'
      },
      async onopen(response) {
        if (response.ok && response.headers.get('content-type').includes(EventStreamContentType)) {
          return // everything's good
        } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
          // client-side errors are usually non-retriable:
          throw new FatalError()
        } else {
          throw new RetriableError()
        }
      },
      onmessage(msg) {
        if (msg.event === 'FatalError') {
          throw new FatalError(msg.data)
        }
        if (!msg.event) {
          resolve(msg.data.replaceAll('\\n', '\n'), false)
        } else if (msg.event === 'item_id') {
          itemIdCallback && itemIdCallback(msg.data)
        }
      },
      onclose() {
        resolve('', true)
      },
      onerror(err) {
        console.error(err)
        reject(err)
        throw new Error(err)
      }
    })
  }

  static items({ dialog_id, last_id }) {
    return request.get('/chat-api/v1/gpt/dialog/items', {
      params: { dialog_id, last_id }
    }).then(res => {
      return (res || []).map(el => {
        el.userMsgFlag = el.from_user_id > 0
        el.hasError = false
        el.loading = false
        el.stopped = el.status === 2
        return el
      })
    })
  }

  static descriptorExampleList() {
    return request.get('/chat-api/v1/gpt/descriptor-example/random-list', {
      params: {
        v: new Date().getTime()
      }
    })
  }
}

